import { tryOnUnmounted, useDebounceFn, useTimeoutFn } from '@vueuse/core';
import type { EChartsOption } from 'echarts';
import type { Ref } from 'vue';
import { computed, nextTick, ref, unref, watch } from 'vue';
import { useEventListener } from '..';

import echarts from './echarts';

/**
 * @description 调用 echarts 传入 echarts 对应的 ref 即可
 * @author wfd
 * @date 2022/11/14 20:14
 * @example
 * @param {Ref<HTMLDivElement>} elRef
 * @param {"light" | "dark" | "default"} theme
 * @returns {{echarts: {helper: helper_d, vector: vector_d, registerTheme: any, env: any, matrix: matrix_d, registerLoading: any, color: color_d, init: any, disConnect: any, registerUpdateLifecycle: any, PatternObject: any, registerProcessor: any, LinearGradientObject: any, Payload: any, parseGeoJSON: any, registerTransform: any, SetOptionOpts: any, dispose: any, format: format_d, util: util_d$1, throttle: any, ECharts: EChartsType, registerPostInit: any, registerLayout: any, zrender: zrender_d, Model: any, ImagePatternObject: any, EChartsType: any, Color: string | LinearGradientObject | RadialGradientObject | ImagePatternObject | SVGPatternObject, extendChartView: any, SVGPatternObject: any, parseGeoJson: (geoJson: (GeoJSON | GeoJSONCompressed), nameProperty: string) => GeoJSONRegion[], time: time_d, innerDrawElementOnCanvas: (ctx: CanvasRenderingContext2D, el: Displayable) => void, connect: any, dataTool: any, number: number_d, setCanvasCreator: any, registerLocale: any, SetOptionTransitionOptItem: any, ElementEvent: any, extendSeriesModel: any, ChartView: any, registerAction: any, registerMap: any, ResizeOpts: any, ComponentModel: any, version: any, PRIORITY: any, extendComponentModel: any, registerCoordinateSystem: any, use: any, registerVisual: any, ComponentView: any, getInstanceById: any, disconnect: any, dependencies: any, getMap: any, graphic: graphic_d, SetOptionTransitionOpt: any, registerPreprocessor: any, zrUtil: util_d, getCoordinateSystemDimensions: any, getInstanceByDom: any, EChartsCoreOption: ECBasicOption, extendComponentView: any, SeriesModel: any, Axis: any, RadialGradientObject: any, ComposeOption: any, setPlatformAPI: any, registerPostUpdate: any, List: SeriesData}, setOptions: (options: EChartsOption, clear?: boolean) => void, resize: () => void, getInstance: () => (EChartsType | null)}}
 */
export function useECharts (
  elRef: Ref<HTMLDivElement>,
  theme: 'light' | 'dark' | 'default' = 'default'
) {
  const getDarkMode = computed(() => {
    
    return 'default';
  });
  let chartInstance: echarts.ECharts | null = null;
  let resizeFn: AnyFunction<any> = resize;
  const cacheOptions = ref({}) as Ref<EChartsOption>;
  let removeResizeFn: AnyFunction<any> = () => {};
  
  resizeFn = useDebounceFn(resize, 200);
  
  const getOptions = computed(() => {
    if (getDarkMode.value !== 'dark') {
      return cacheOptions.value as EChartsOption;
    }
    return {
      backgroundColor: 'transparent',
      ...cacheOptions.value
    } as EChartsOption;
  });
  
  function initCharts (t = theme) {
    const el = unref(elRef);
    if (!el || !unref(el)) {
      return;
    }
    
    chartInstance = echarts.init(el, t);
    const { removeEvent } = useEventListener(
      window,
      'resize',
      resizeFn
    );
    removeResizeFn = removeEvent;
    if (el.offsetHeight === 0) {
      useTimeoutFn(() => {
        resizeFn();
      }, 30);
    }
  }
  
  function setOptions (options: EChartsOption, clear = true) {
    cacheOptions.value = options;
    if (unref(elRef)?.offsetHeight === 0) {
      useTimeoutFn(() => {
        setOptions(unref(getOptions));
      }, 30);
      return;
    }
    nextTick(() => {
      useTimeoutFn(() => {
        if (!chartInstance) {
          initCharts(getDarkMode.value as 'default');
          
          if (!chartInstance) return;
        }
        clear && chartInstance?.clear();
        
        chartInstance?.setOption(unref(getOptions));
      }, 30);
    });
  }
  
  function resize () {
    chartInstance?.resize();
  }
  
  watch(
    () => getDarkMode.value,
    (theme) => {
      if (chartInstance) {
        chartInstance.dispose();
        initCharts(theme as 'default');
        setOptions(cacheOptions.value);
      }
    }
  );
  
  tryOnUnmounted(() => {
    if (!chartInstance) return;
    removeResizeFn();
    chartInstance.dispose();
    chartInstance = null;
  });
  
  function getInstance (): echarts.ECharts | null {
    if (!chartInstance) {
      initCharts(getDarkMode.value as 'default');
    }
    return chartInstance;
  }
  
  return {
    setOptions,
    resize,
    echarts,
    getInstance
  };
}
